home *** CD-ROM | disk | FTP | other *** search
/ Aminet 40 / Aminet 40 (2000)(Schatztruhe)[!][Dec 2000].iso / Aminet / util / cdity / ModeProSrc.lha / Daemon / ImageBackFill.c < prev    next >
C/C++ Source or Header  |  1998-08-14  |  13KB  |  345 lines

  1. /*
  2. ** $VER: ImageBackFill.c 1.231 (19.3.95)
  3. **
  4. ** Tests backfill hooks in screens
  5. **
  6. ** Make>> smake
  7. **
  8. ** (W) 1992-95 by Pierre Carrette & Walter Dörwald
  9. */
  10.  
  11. //#define DEBUG
  12. #include <debug.h>
  13. #include "mp.h"
  14. #include "ImageBackFill.h"
  15. #include "backfill.h"
  16.  
  17. struct Hook *Image_AllocBackfillHook(struct Screen *Scr, struct DefaultNode *DN)
  18. {
  19.   struct BackFillOptions bfo;
  20.   struct BackFillInfo *b;
  21.   
  22.   if(DN->BackdropFile && DataTypesBase)
  23.   {
  24.     if(b=AllocVec(sizeof(*b),MEMF_CLEAR|MEMF_PUBLIC))
  25.     {
  26.       bfo.MaxCopyWidth=
  27.       bfo.MaxCopyWidth=320;
  28.       bfo.CenterX=
  29.       bfo.CenterY=(DN->BackdropFlags & BF_CENTER);
  30.       bfo.OffsetX=0;
  31.       bfo.OffsetY=0;
  32.       bfo.OffsetTitleY=0;
  33.                
  34.       if(LoadBackgroundImage(b,DN->BackdropFile,Scr,&bfo))
  35.       {
  36.         return((struct Hook *)b);
  37.       }
  38.       FreeVec(b);
  39.     }
  40.   }
  41.   return(0);
  42. }
  43.  
  44. void Image_FreeBackfillHook(struct Hook *Hook)
  45. {
  46.   struct BackFillInfo *b;
  47.  
  48.   b=(struct BackFillInfo *)Hook;
  49.  
  50. //  if(b->bd_Loaded)
  51.   {
  52.     UnloadBackgroundImage(b);
  53.   }
  54.   FreeVec(b);
  55. }
  56.       
  57. // this seems to be a bug (or feature) in SAS/C: -6%5 gives -1 instead of 4
  58. #define MOD(x,y) ((x)<0 ? (y)-((-(x))%(y)) : (x)%(y))
  59.  
  60. #define RECTSIZEX(r) ((r)->MaxX-(r)->MinX+1)
  61. #define RECTSIZEY(r) ((r)->MaxY-(r)->MinY+1)
  62.  
  63. /****** CopyTiledBitMap ****************************************************************************
  64. *
  65. *   NAME
  66. *    CopyTiledBitMap() -- fill bitmap with bitmap pattern
  67. *
  68. *   SYNOPSIS
  69. *    CopyTiledBitMap(Src,SrcOffsetX,SrcOffsetY,SrcSizeX,SrcSizeY,Dst,DstBounds)
  70.  
  71. *    void CopyTiledBitMap(struct BitMap *,WORD,WORD,WORD,WORD,struct BitMap *,struct Rectangle *)
  72. *
  73. *   FUNCTION
  74. *    fills the destination bitmap with repeated (tiled) copies of the source bitmap
  75. *
  76. *   INPUTS
  77. *    Src = source bitmap.
  78. *    SrcOffsetX = offset (in x direction) to use in the blit.
  79. *    SrcOffsetY = offset (in y direction) to use in the blit.
  80. *                 The pixel at position (SrcOffsetX,SrcOffsetY) in the source bitmap
  81. *                 will be the first visible one in the upper left corner of DstBounds.
  82. *    SrcSizeX = width of the source bitmap Src.
  83. *    SrcSizeY = height of the source bitmap Src.
  84. *    Dst = destination bitmap.
  85. *    DstBounds = this rectangle in the destination bitmap will be filled.
  86. *
  87. *   RESULT
  88. *    None.
  89. *
  90. *   EXAMPLE
  91. *    This function is most useful in backfill hooks.
  92. *
  93. *   NOTES
  94. *    The following relations must hold:
  95. *        0 <= SrcOffsetX < SrcSizeX
  96. *        0 <= SrcOffsetY < SrcSizeY
  97. *    I.e. if calculating the offset involves some kind of modulo-operations
  98. *    they have to be done before calling this function
  99. *
  100. *   BUGS
  101. *
  102. *   AUTHOR
  103. *    Copyright © 1995 by Walter Dörwald
  104. *
  105. *   SEE ALSO
  106. *
  107. ****************************************************************************************************
  108. *
  109. *    This function uses an "exponential" blit to fill the dest rect.
  110. *    Suppose we have a 64×64 source bitmap and want to use offset 0,0
  111. *    (i.e. the upper left corner of the source bitmap is copied to the
  112. *    upper left corner of the dest rect. Let the dest rect be 320×320
  113. *    with upper left corner (0,0). Thus we'll blit 5×5 copies of the
  114. *    source bitmap to the destination.
  115. *    Doing this with two nested loops would thus require 25 blits, or
  116. *    x·y blits for x horizontal tiles and y vertical tiles.
  117. *    First one copy of the source bitmap is blitted to the upper left
  118. *    corner of the dest rect:
  119. *
  120. *        #....
  121. *        .....
  122. *        .....
  123. *        .....
  124. *        .....
  125. *
  126. *    This copy is then blitted to the right:
  127. *
  128. *        ##...
  129. *        .....
  130. *        .....
  131. *        .....
  132. *        .....
  133. *
  134. *    *Both* copies are once again blitted to the right
  135. *
  136. *        ####.
  137. *        .....
  138. *        .....
  139. *        .....
  140. *        .....
  141. *
  142. *    Finally the first row is filled with one blit:
  143. *
  144. *        #####
  145. *        .....
  146. *        .....
  147. *        .....
  148. *        .....
  149. *
  150. *    Now the same is done vertically to fill the complete rect:
  151. *
  152. *        #####   #####   #####
  153. *        #####   #####   #####
  154. *        .....   #####   #####
  155. *        .....   #####   #####
  156. *        .....   .....   #####
  157. *
  158. *    This requires 7 blit, or generally 1+ceil(log_2(x))+ceil(log_2(y))
  159. *
  160. *    The blits are done first in x direction and then in y direction
  161. *    to minimize potential masking effects at the left and right border.
  162. *
  163. *    If the offsets into the source bitmap are not 0, part of a second tile
  164. *    is blitted to the destination bitmap to once again get a tile of the
  165. *    required size.
  166. */
  167.  
  168. void CopyTiledBitMap(struct BitMap *Src,WORD SrcOffsetX,WORD SrcOffsetY,WORD SrcSizeX,WORD SrcSizeY,struct BitMap *Dst,struct Rectangle *DstBounds)
  169. {
  170.     WORD FirstSizeX;  // the width of the rectangle to blit as the first column
  171.     WORD FirstSizeY;  // the height of the rectangle to blit as the first row
  172.     WORD SecondMinX;  // the left edge of the second column
  173.     WORD SecondMinY;  // the top edge of the second column
  174.     WORD SecondSizeX; // the width of the second column
  175.     WORD SecondSizeY; // the height of the second column
  176.     WORD Pos;         // used as starting position in the "exponential" blit
  177.     WORD Size;        // used as bitmap size in the "exponential" blit
  178.  
  179.     FirstSizeX = MIN(SrcSizeX-SrcOffsetX,RECTSIZEX(DstBounds)); // the width of the first tile, this is either the rest of the tile right to SrcOffsetX or the width of the dest rect, if the rect is narrow
  180.     SecondMinX = DstBounds->MinX+FirstSizeX; // the start for the second tile (if used)
  181.     SecondSizeX = MIN(SrcOffsetX,DstBounds->MaxX-SecondMinX+1); // the width of the second tile (we want the whole tile to be SrcSizeX pixels wide, if we use SrcSizeX-SrcOffsetX pixels for the left part we'll use SrcOffsetX for the right part)
  182.  
  183.     FirstSizeY = MIN(SrcSizeY-SrcOffsetY,RECTSIZEY(DstBounds)); // the same values are calculated for y direction
  184.     SecondMinY = DstBounds->MinY+FirstSizeY;
  185.     SecondSizeY = MIN(SrcOffsetY,DstBounds->MaxY-SecondMinY+1);
  186.  
  187.     BltBitMap(Src,SrcOffsetX,SrcOffsetY,Dst,DstBounds->MinX,DstBounds->MinY,FirstSizeX,FirstSizeY,0xC0,-1,NULL); // blit the first piece of the tile
  188.     if (SecondSizeX>0) // if SrcOffset was 0 or the dest rect was to narrow, we won't need a second column
  189.         BltBitMap(Src,0,SrcOffsetY,Dst,SecondMinX,DstBounds->MinY,SecondSizeX,FirstSizeY,0xC0,-1,NULL);
  190.     if (SecondSizeY>0) // is a second row necessary?
  191.     {
  192.         BltBitMap(Src,SrcOffsetX,0,Dst,DstBounds->MinX,SecondMinY,FirstSizeX,SecondSizeY,0xC0,-1,NULL);
  193.         if (SecondSizeX>0)
  194.             BltBitMap(Src,0,0,Dst,SecondMinX,SecondMinY,SecondSizeX,SecondSizeY,0xC0,-1,NULL);
  195.     }
  196.  
  197.     // this loop generates the first row of the tiles
  198.     for (Pos = DstBounds->MinX+SrcSizeX,Size = MIN(SrcSizeX,DstBounds->MaxX-Pos+1);Pos<=DstBounds->MaxX;)
  199.     {
  200.         BltBitMap(Dst,DstBounds->MinX,DstBounds->MinY,Dst,Pos,DstBounds->MinY,Size,MIN(SrcSizeY,RECTSIZEY(DstBounds)),0xC0,-1,NULL);
  201.         Pos += Size;
  202.         Size = MIN(Size<<1,DstBounds->MaxX-Pos+1);
  203.     }
  204.  
  205.     // this loop blit the first row down several times to fill the whole dest rect
  206.     for (Pos = DstBounds->MinY+SrcSizeY,Size = MIN(SrcSizeY,DstBounds->MaxY-Pos+1);Pos<=DstBounds->MaxY;)
  207.     {
  208.         BltBitMap(Dst,DstBounds->MinX,DstBounds->MinY,Dst,DstBounds->MinX,Pos,RECTSIZEX(DstBounds),Size,0xC0,-1,NULL);
  209.         Pos += Size;
  210.         Size = MIN(Size<<1,DstBounds->MaxY-Pos+1);
  211.     }
  212. }
  213.  
  214. // This function must be compiled without stack checking
  215. static void __saveds __asm WindowPatternBackFillFunc(register __a0 struct Hook *Hook,register __a2 struct RastPort *RP,register __a1 struct BackFillMsg *BFM)
  216. {
  217.     WORD OffsetX; // the offset within the tile in x direction
  218.     WORD OffsetY; // the offset within the tile in y direction
  219.  
  220.     struct BackFillInfo *BFI = (struct BackFillInfo *)Hook; // get the data for our backfillhook (but __saveds is nonetheless required because this function needs GfxBase)
  221.  
  222.  
  223.     OffsetX = BFM->Bounds.MinX-BFI->Options.OffsetX; // The first tile normally isn't totally visible => calculate the offset (offset 0 would mean that the left edge of the damage rectangle coincides with the left edge of a tile)
  224.     if (BFI->Options.CenterX) // horizontal centering?
  225.         OffsetX -= (BFI->Screen->Width-BFI->BitMapHeader->bmh_Width)/2;
  226.  
  227.     OffsetY = BFM->Bounds.MinY-BFI->Options.OffsetY; // The same values are calculated for y direction
  228.     if (BFI->Options.OffsetTitleY) // shift the tiles down?
  229.         OffsetY -= BFI->Screen->BarHeight+1;
  230.     if (BFI->Options.CenterY) // horizontal centering?
  231.         OffsetY -= (BFI->Screen->Height-BFI->BitMapHeader->bmh_Height)/2;
  232.  
  233.     CopyTiledBitMap(BFI->BitMap,MOD(OffsetX,BFI->BitMapHeader->bmh_Width),MOD(OffsetY,BFI->BitMapHeader->bmh_Height),BFI->CopyWidth,BFI->CopyHeight,RP->BitMap,&BFM->Bounds);
  234. }
  235.  
  236. // this function calculates the sizes to be used for the copy of the bitmap
  237. static void CalculateCopySizes(struct BackFillInfo *BFI)
  238. {
  239.     BFI->CopyWidth  = (BFI->BitMapHeader->bmh_Width>BFI->Options.MaxCopyWidth)   ? BFI->BitMapHeader->bmh_Width  : BFI->Options.MaxCopyWidth -BFI->Options.MaxCopyWidth%BFI->BitMapHeader->bmh_Width;
  240.     BFI->CopyHeight = (BFI->BitMapHeader->bmh_Height>BFI->Options.MaxCopyHeight) ? BFI->BitMapHeader->bmh_Height : BFI->Options.MaxCopyHeight-BFI->Options.MaxCopyHeight%BFI->BitMapHeader->bmh_Height;
  241. }
  242.  
  243. BOOL LoadBackgroundImage(struct BackFillInfo *BFI,STRPTR PicName,struct Screen *Scr,struct BackFillOptions *BFO)
  244. {
  245.   LONG stc,depth; // screen true color
  246.   
  247.     if (DataTypesBase) // safety check, if not used with V39++
  248.     {
  249.         memset(BFI,0,sizeof(*BFI));
  250.         BFI->Hook.h_Entry = (ULONG (*)())WindowPatternBackFillFunc;
  251.         BFI->Screen = Scr;
  252.         BFI->Options = *BFO;
  253.  
  254.     depth=GetBitMapAttr(Scr->RastPort.BitMap,BMA_DEPTH);
  255.  
  256.     stc=(depth>8 ? 1 : 0);
  257.  
  258. //    DKP("Depth=%ld  %ld\n",depth,stc);
  259.  
  260.         if (BFI->PictureObject = NewDTObject(PicName,
  261.                                              DTA_SourceType       ,DTST_FILE,
  262.                                              DTA_GroupID          ,GID_PICTURE,
  263.                                              PDTA_Remap           ,(stc ? FALSE : TRUE),
  264.                                              PDTA_Screen          ,Scr,
  265.                                              PDTA_FreeSourceBitMap,TRUE,
  266.                                          
  267.                                          PDTA_DestMode,        (stc ? PMODE_V43 : PMODE_V42),
  268.                                          
  269.                                          PDTA_UseFriendBitMap ,1,
  270.                                              OBP_Precision        ,PRECISION_EXACT,
  271.                                              TAG_DONE))
  272.         {
  273.             if (DoMethod(BFI->PictureObject,DTM_PROCLAYOUT,NULL,1))
  274.             {
  275.                 struct BitMap *BitMap;
  276.  
  277.         BitMap=0;
  278.  
  279.                 GetDTAttrs(BFI->PictureObject,PDTA_BitMapHeader,        &BFI->BitMapHeader,
  280.                                       (stc ? PDTA_BitMap : PDTA_DestBitMap),          &BitMap,
  281. //                                    PDTA_DestMode,            &destmode,
  282.                                       TAG_DONE);
  283.         
  284.                 if (!BitMap)
  285.                     GetDTAttrs(BFI->PictureObject,PDTA_BitMap,&BitMap,TAG_DONE);
  286.           
  287.                 if(BitMap)
  288.                 {
  289.                     LONG Depth = GetBitMapAttr(BitMap,BMA_DEPTH);
  290.  
  291.                     CalculateCopySizes(BFI);
  292.  
  293.                     // the bitmap is copied to a friend bitmap of the screen to speed up rendering with gfxboards (no c2p/p2c!); this additionally allows to use this copy as a "picture cache", i.e. if the picture is 2x2 the copy can be made 16x16 (with 64 tiles) or whatever to speed up rendering
  294.                     if (BFI->BitMap = AllocBitMap(BFI->CopyWidth,BFI->CopyHeight,Depth, BMF_MINPLANES ,(stc ? BitMap: Scr->RastPort.BitMap)))
  295.                     {
  296.                         struct Rectangle CopyBounds;
  297.                         CopyBounds.MinX = 0;
  298.                         CopyBounds.MinY = 0;
  299.                         CopyBounds.MaxX = BFI->CopyWidth-1;
  300.                         CopyBounds.MaxY = BFI->CopyHeight-1;
  301.  
  302.  
  303. /*            
  304.             if(CyberGfxBase && destmode==PMODE_V43)
  305.             {
  306.               struct pdtBlitPixelArray bpa;
  307.               
  308.               bpa.MethodID=PDTM_READPIXELARRAY;
  309.               bpa.pbpa_PixelArray=;      /* Source PixelArray                                         */
  310.               bpa.pbpa_PixelArrayMode=;  /* Format Mode of the Source PixelArray; see cybergraphics.h */
  311.               bpa.pbpa_PixelArrayMod=;   /* Bytes to add to the next line in the Source PixelArray    */
  312.               bpa.pbpa_LeftEdge=;        /* XStart of the Dest                                        */
  313.               bpa.pbpa_TopEdge=;         /* YStart of the Dest                                        */
  314.               bpa.pbpa_Width=;           /* Width of the Source PixelArray                            */
  315.               bpa.pbpa_Height=;          /* Height of the Source PixelArray                           */
  316.               
  317.               
  318.               DoMethod(
  319.                             
  320.               CopyTiledBitMap(BFI->BitMap,0,0,BFI->BitMapHeader->bmh_Width,BFI->BitMapHeader->bmh_Height,BFI->BitMap,&CopyBounds); // blit the tiles to the bitmap
  321.             }
  322.             else*/
  323.             {
  324.                           CopyTiledBitMap(BitMap,0,0,BFI->BitMapHeader->bmh_Width,BFI->BitMapHeader->bmh_Height,BFI->BitMap,&CopyBounds); // blit the tiles to the bitmap
  325.             }
  326.                         return (TRUE);
  327.                     }
  328.                 }
  329.             }
  330.         }
  331.     UnloadBackgroundImage(BFI);
  332.         //memset(BFI,0,sizeof(*BFI));
  333.     }
  334.     return (FALSE);
  335. }
  336.  
  337. void UnloadBackgroundImage(struct BackFillInfo *BFI)
  338. {
  339.     WaitBlit();
  340.     // both frees work with NULL
  341.     FreeBitMap(BFI->BitMap);
  342.     DisposeDTObject(BFI->PictureObject); // datatype object is freed here, because - although a different bitmap is used for blitting to the screen - the pens have to stay allocated
  343.     memset(BFI,0,sizeof(*BFI));
  344. }
  345.